Skip to content

feat(scratch-vm): 甲子園ブロックの固定値/状態実装(MockClient)#742

Open
takaokouji wants to merge 4 commits into
developfrom
feature/issue-739-koshien-mock-client
Open

feat(scratch-vm): 甲子園ブロックの固定値/状態実装(MockClient)#742
takaokouji wants to merge 4 commits into
developfrom
feature/issue-739-koshien-mock-client

Conversation

@takaokouji

Copy link
Copy Markdown

Summary

スモウルビー甲子園拡張機能のブロックを、編集機上でクリック/実行したときに意味のある固定値を返し、引数のリストを実際に更新するようにしました(未接続モード)。Epic #738 の Phase P1。

これまで各ブロックは -1 / undefined / 空 Promise を返すだけで意味のある挙動をしませんでした。

アーキテクチャ

KoshienClientインターフェース化し、未接続時用に固定値を返す MockClient を実装。ブロックメソッドは client 越しに値を得るため、将来 #741 で実サーバー通信する RemoteClient と差し替え可能です。

ブロックメソッド → KoshienClient(interface) → MockClient(固定値) / RemoteClient(将来)

Changes Made

  • KoshienClient(基底インターフェース)+ MockClient(固定値)を追加し、コンストラクタで MockClient を使用
  • ブロックメソッドを client 経由に接続:
    • map0(空間)
    • mapAll → 15×15 全空間の文字列 "000000000000000,…"(15行)
    • mapFrom → MAP 変数のマップ文字列をパースして該当セル(解決不能なら 0
    • targetCoordinate → player=1:1 / goal=13:13 / other_player=enemy=7:7(x/y/position 対応)
    • calcGoalRoute → 結果リストに [player, goal] を書き込む
    • calcRoute → 結果リストに [SRC, DST] を書き込む
    • locateObjects → 結果リストに固定座標を書き込む
    • getMapArea / moveTo / setItem / turnOver / setMessage → 安全な no-op
  • リスト書き込みは target.lookupVariableByNameAndType(name, 'list') で取得し value を置換(未指定 ' ' や未発見時は no-op)

Test Coverage

  • test/unit/extension_koshien.js(tap)に固定値・リスト書き込み・no-op のテストを追加(計 74 アサーション pass)
  • lint pass(eslint 0 errors / 0 warnings on 変更ファイル、prettier OK)

Definition of Done

  • 全ブロックが意味のある固定値を返す
  • calc系/locate が指定リストへ実書き込み
  • ユニットテスト pass(tap)
  • lint pass
  • CI green
  • ブラウザ確認(Playwright MCP): 甲子園ブロックをクリックして固定値表示・calc系でリストモニタ更新

Related Issues

Refs #739 / Epic #738

🤖 Generated with Claude Code

甲子園拡張機能のブロックがクリック/実行時に意味のある値を返すようにした。
KoshienClient をインターフェース化し、未接続時用の固定値クライアント
MockClient を実装してブロックメソッドを接続した(将来の RemoteClient と
差し替え可能な構造)。

- map=0(空間), mapAll=15x15 全空間文字列, mapFrom=マップ文字列をパース
- targetCoordinate: player=1:1 / goal=13:13 / other_player=enemy=7:7
- calcRoute/calcGoalRoute/locateObjects は指定リスト変数へ実際に書き込む
- getMapArea/moveTo/setItem/turnOver/setMessage は安全な no-op

Refs #739

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

@takaokouji

Copy link
Copy Markdown
Author

✅ ブラウザ DoD 確認(プレビューで実機検証)

プレビュー https://smalruby.jp/smalruby3-editor/feature/issue-739-koshien-mock-client/ で、デプロイ済みブランチコードの甲子園ブロックを Playwright MCP で検証(CI も全 green):

  • レポーターの固定値: map("0:0")0player"1:1"goal"13:13"enemy"7:7"player の x1map_all → 15 行×15列の全空間文字列。
  • リスト書き込み(ステージのリスト変数 route に対して):
    • calc_goal_route["1:1", "13:13"]
    • calc_route(src:"2:3", dst:"4:5")["2:3", "4:5"]
    • locate_objects["7:7"]

→ 「ブロックをクリックすると固定値が表示され、calc 系でリストに座標が反映される」を確認。DoD のブラウザ項目を満たしました。

takaokouji and others added 3 commits June 14, 2026 12:49
…en blocks

When not connected to a real game server the koshien blocks previously
returned flat placeholders (all-zero map, [src,dst] route, fixed [7:7]).
During the first explanation a user is almost always disconnected, so
clicking a block gave no sense of what it really returns.

Now the mock derives every value from a single source of truth — a fixed,
believable 15x15 sample map (MOCK_MAP) with walls, water, a goal and
scattered items — via new pure helpers in map-utils.js (shared-ready so the
remote client can adopt the same Dijkstra/scan logic):

- map / map_all / map_from -> real cell codes from the sample map
- calc_goal_route / calc_route -> actual shortest path (multi-waypoint),
  honoring the EXCEPT_CELLS list
- locate_objects -> the items really present within range
- target_coordinate -> positions consistent with the map

Phase 2 (pseudo state): move_to moves the mock player, set_item marks the
map, turn_over advances a counter, so repeated runs feel alive.

Reset timing: the mock world resets to its initial state on green flag
(PROJECT_START), on stop (PROJECT_STOP_ALL), and when connect_game runs —
the natural "new game" moments, so a demo can be replayed cleanly.

Tests: rewrote extension_koshien.js expectations for the believable values
and added koshien_map_utils.js for the pure helpers (146 assertions, lint
clean).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The mock sample map was a hand-made 15x15 grid. The real Smalruby Koshien
field is 17x17 surrounded by an unbreakable wall border (verified against the
2024 default map "map_01": top/left edge = code 2, bottom/right edge = code 1;
breakable walls are 5).

- MOCK_MAP is now map_01 with its item layer merged into letters (a-e/A-D),
  exactly how the real server encodes my_map (ITEM_MARKS). Player starts (5,1)
  and (10,1), goal '3' at (8,9), enemy guards the goal.
- map-utils.locateObjects: sq_size is the full square side, not a radius
  (real game uses radius = (sq_size-1)/2); fixed an over-wide scan window.

Tests updated to the real map values + a new assertion that the whole field
is bordered by unbreakable walls.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The mock now mirrors the real game's exploration: the player's "my map"
starts fully unexplored (all -1) and is revealed 5x5 at a time by
get_map_area. map / map_all / calc_route / locate_objects all work off this
gradually-revealed my map, so locate_objects finds nothing until the area is
explored and calc_route plans through fog (unexplored = passable). moveTo
passability is checked against the ground-truth map, and set_item marks the
ground truth (visible once that cell is revealed). Reset clears the my map
back to fully unexplored.

map-utils gains createUnexploredGrid + revealArea (clamped window, matching
the server's getMapArea range). Tests reworked to the explore-then-read flow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant